﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using ProgNetComponentsDx.Browsers;
using ProgNetComponentsDx.Options;
using System.Threading;
using BuildHelper.Setup.BazyDanych;
using ProgNetComponents.Data.SqlCe;

namespace BuildHelper.BHTasks
{
    public class DbUpdateTask : BaseTask
    {
        static DbUpdateTask t = new DbUpdateTask();
        public static void UpdateAll(bool showinfo = true)
        {
            if (!t.IsRunning)
            {
                t.ShowInfoAlert = showinfo;
                t.Run();
            }
            else
            {
                FormMain.Instance.ShowErrorDialog("Operacja w toku.");
            }
        }
        protected override string GetTaskName()
        {
            return "Uaktualnianie baz danych";
        }

        public DbUpdateTask()
        {
            this.AlertImage = FormMain.Instance.MenuControl.commonImageCollectionFull1.Images[96];
        }
        
        protected override void RunTask()
        {
            Task t = Task.Factory.StartNew(UpdateDB);
        }
        
        CancellationTokenSource cts = new CancellationTokenSource();
        Setup.BazyDanych.BazyDanychDataSet ds = new BazyDanychDataSet();
        
        public Setup.BazyDanych.BazyDanychDataSet ModifiedDataSet
        {
            get { return ds; }
        }
        public bool Modified { get; private set; }

        private void UpdateDB()
        {
            Modified = false;
            ds.Clear();
            ds.AcceptChanges();
            using (SqlCeDataManager m = new SqlCeDataManager())
            {
                m.AutoLogExceptions = true;
                m.AddTableDef(ds.STP_BAZY_DANYCH);
                m.FillDataSet(ds);
            }
            DataTable dt = BrowserCache.GetBrowserData(Init.InitFormBrowserNames.Setup.Srodowiska).Copy();
            List<DataRow> envsRows = new List<DataRow>();
            bool updateOnlyActive = OptionCache.GetOptionBoolValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.BazyDanych.UaktualniajTylkoDzialajace);

            foreach (DataRow r in dt.Rows)
            {
                if (!updateOnlyActive || r["STP_SR_DZIALA"].AsBool())
                {
                    envsRows.Add(r);
                }
            }
            //envsRows.Clear();
            //DataRow rq = dt.SelectFirstRow("STP_SR_NAZWA = 'Q115'");
            //envsRows.Add(rq);
            int maxThreads = OptionCache.GetOptionValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.Srodowiska.MaxThreads).AsInt(1);
            ParallelOptions op = new ParallelOptions();
            op.MaxDegreeOfParallelism = maxThreads;
            op.CancellationToken = this.cts.Token;
            this.MaxItems = envsRows.Count;
            this.Progress = 0;
            try
            {
                Parallel.ForEach(envsRows, op, GetData);
            }
            catch
            {

            }
            finally
            {
                EndTask(TaskStatus.Finished);
            }
        }
        protected override void FinalizeTask(TaskStatus status)
        {
            if (status != TaskStatus.Canceled)
            {
                if (ds.HasChanges())
                {
                    using (SqlCeDataManager m = new SqlCeDataManager())
                    {
                        m.AutoLogExceptions = true;
                        m.AddTableDef(ds.STP_BAZY_DANYCH);
                        Modified = m.UpdateDataSet(ds);
                        if (!Modified)
                        {
                            status = TaskStatus.FinishedWithError;
                            DataRow[] rows = ds.STP_BAZY_DANYCH.Select(null, null, DataViewRowState.Added | DataViewRowState.ModifiedCurrent);
                            List<string> invalidEnvs = new List<string>();
                            foreach (DataRow r in rows)
                            {
                                if (m.UpdateRows(false, r) != ProgNetComponents.Data.RowsUpdateResults.AllSucceeded)
                                {
                                    invalidEnvs.Add(r["STP_BD_NAZWA"].AsString());
                                }
                            }
                            if (invalidEnvs.Count > 0 && Program.IsDebug)
                            {
                                ("Invalid envs = " + invalidEnvs.AsString(", ")).LogDebug();
                            }
                        }
                    }
                }
            }
            base.FinalizeTask(status);
        }

        private void GetData(DataRow row)
        {
            if (IsRunning)
            {
                string env = row["STP_SR_NAZWA"].ToString();
                Tools.DbData e = Tools.GetDbData(env);
                Progress++;

                if (e != null)
                {
                    if (e.UserName.IsNull() || e.UserName.Length > 50)
                        return;
                    if (OptionCache.GetOptionBoolValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.BazyDanych.AutoAddTnsNames))
                    {
                        GlobalTools.DBTools.AddTnsNames(e.EnvName, e.Host, e.Port.AsString(), e.Service, e.Sid);
                    }

                    DataRow r = ds.STP_BAZY_DANYCH.SelectFirstRow("STP_BD_NAZWA = " + env.EscapeSql());
                    if (r == null)
                    {
                        r = ds.STP_BAZY_DANYCH.NewRow();
                        r["STP_BD_NAZWA"] = e.EnvName;
                        ds.STP_BAZY_DANYCH.Rows.Add(r);
                    }

                    r.SetColVal("STP_BD_", e.Host);
                    r.SetColVal("STP_BD_HOST", e.Host);
                    if (e.Port.IsNotNull())
                        r.SetColVal("STP_BD_PORT", e.Port);
                    else
                        r.SetColVal("STP_BD_PORT", DBNull.Value);
                    r.SetColVal("STP_BD_WLASNA", false);
                    r.SetColVal("STP_BD_SERVICE", e.Service);
                    r.SetColVal("STP_BD_SID", e.Sid);
                    r.SetColVal("STP_BD_USER", e.UserName);
                    r.SetColVal("STP_BD_PASS", e.Pass);
                    r.SetColVal("STP_BD_WERSJA", e.Wersja);
                    r.SetColVal("STP_BD_DATA_AKTUALIZACJI", DateTime.Now);
                }
            }
        }
    }
}
